/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	main.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	20190509
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/
//两种下载方法 ETH_DOWNLOAD 或 COM_DOWNLOAD


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "includes.h"
#include "log_console.h"
#include "timer.h"
#include "spi_flash.h"
#include "iap.h"
#include "fatfs.h"
#include "sys_tick.h"

/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

#define BOOTLOADER_FLASH_SIZE	0x40000

#define IAP_ADDR	APP_FLASH_ADDR_START

#define SPI_READ_DATA_SIZE	W25X_SECTOR_SIZE
/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/
static uint8_t iap_app_index(void);
static void Stm32_Clock_Init(uint32_t plln,uint32_t pllm,uint32_t pllp,uint32_t pllq);
static void IapProgramRun(void);
static void Load_app(uint8_t iap_index);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
extern log_console_t m_log_console;
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/
static uint8_t spi_read_buff[SPI_READ_DATA_SIZE];

/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*                                                main()
*
* Description : This is the standard entry point for C code.  It is assumed that your code will call
*               main() once you have performed all necessary initialization.
*
* Arguments   : none
*
* Returns     : none
*********************************************************************************************************
*/

int main(void)
{	
	char file_name[32];
	FIL file;
	FATFS* fatfs;
	uint8_t iap_index = 0;
	Stm32_Clock_Init(160,5,2,4);
	system_cfg_init();
	SysTick->CTRL = SysTick->CTRL & (~SysTick_CTRL_ENABLE_Msk);
	
	bsp_uart_reveive_byte(m_log_console.p_uart,&iap_index,1000);
//	if(iap_index == 0)
//		iap_index = SYSTEM_CFG->iap_index;
//	else
//		iap_index -= '0';
	if(iap_index < IAP_INDEX_MAX && iap_index > 0)
	{
		memset(file_name,0,sizeof(file_name));
		Trace_Log("Bootloader get load index %d;\r\n",iap_index);
		sprintf(file_name,"0://app%d.bin",iap_index);
		if(NULL == fatfs_init(0) || FR_OK != f_open(&file,file_name,FA_READ))
		{
			Trace_Log("Can't open file %s !\r\n");
		}
		else
		{
			Trace_Log("Open file %s success,start load to MCU flash.\r\nDO NOT CLOSE THE POWER DURING LOADING!!!\r\n",file_name);
			iap_from_file(&file);
			Trace_Log("IAP load complete,start app !\r\n");
		}
		f_close(&file);
	}
	else
	{
		Trace_Log("Do not iap,start app !\r\n");
	}
	SysTick->CTRL = SysTick->CTRL & (~SysTick_CTRL_ENABLE_Msk);
	log_console_wait_cplt();
	bsp_timer_deinit();
	IapProgramRun();
}
static void Load_app(uint8_t iap_index)
{
//	if(iap_index == SYSTEM_IAP_NONE)
//		return;
//	
//	uint32_t addr_offset=0;
//	
//	uint32_t new_version;
//	uint32_t spi_addr;
//	uint32_t app_size = SYSTEM_APP_FLASH_MAX_SIZE;
//	switch(iap_index)
//	{
//		case SYSTEM_IAP_APP1:
//			spi_addr = SYSTEM_APP1_FLASH_ADDR;
//			new_version=SYSTEM_CFG->app1_fw_version;
////			app_size=SYSTEM_CFG->app1_fw_size;
//			break;
//		case SYSTEM_IAP_APP2:
//			spi_addr = SYSTEM_APP2_FLASH_ADDR;
//			new_version=SYSTEM_CFG->app2_fw_version;
////			app_size=SYSTEM_CFG->app2_fw_size;
//			break;
//		case SYSTEM_IAP_APP3:
//			spi_addr = SYSTEM_APP3_FLASH_ADDR;
//			new_version=SYSTEM_CFG->app3_fw_version;
////			app_size=SYSTEM_CFG->app3_fw_size;
//			break;
//		default:return;
//	}
//	stm32_flash_erase(IAP_ADDR,app_size);
//	
//	spi_addr = spi_addr;
//	
//	memset(spi_read_buff,0xff,SPI_READ_DATA_SIZE);
//	while(addr_offset < app_size)
//	{
//		if(file_read (spi_addr + addr_offset,spi_read_buff,SPI_READ_DATA_SIZE)!= FILE_SYS_ERRNONE)
//		{
//			Trace_Log("Read SPI flash app failed!\r\n");
//			return;
//		}
//		stm32_flash_write(IAP_ADDR + addr_offset,spi_read_buff,SPI_READ_DATA_SIZE);
//		addr_offset+=SPI_READ_DATA_SIZE;
//	}
//	SYSTEM_CFG->current_fw_version=new_version;
//	Trace_Log("Load app complete!\r\n");
//	file_save_flash(CFG_ADDR_SYSTEM + ((uint32_t)&SYSTEM_CFG->current_fw_version - (uint32_t)&m_system_cfg),(uint8_t*)&new_version,sizeof(new_version),FLASH_WRITE_NORMAL);
}
static void IapProgramRun(void)
{
	uint32_t  IapSpInitVal;
	uint32_t  IapJumpAddr;
	void	(*pIapFun)(void);
	
	/*  */
	IapSpInitVal = (*((volatile uint32_t*)IAP_ADDR));
	if(( ((*((volatile uint32_t*)IAP_ADDR)))&0x2FF00000) == 0x24000000)
	{
		IapJumpAddr = *(uint32_t*)(IAP_ADDR + 4);
	
//		MSR_MSP(IapSpInitVal);
		pIapFun = (void(*)(void))IapJumpAddr;
		__set_MSP(*(__IO uint32_t*) IapSpInitVal);
		(*pIapFun)();
	}
}

static uint8_t iap_app_index(void)
{
//	GPIO_InitTypeDef  GPIO_InitStruct;
//	__HAL_RCC_GPIOG_CLK_ENABLE();

//	GPIO_InitStruct.Pin       = GPIO_PIN_7|GPIO_PIN_8;
//	GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
//	GPIO_InitStruct.Pull      = GPIO_PULLUP;
//	GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
//	HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
//	uint8_t btn_app_index = HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_7)|(HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_8)<<1);
//	uint8_t cfg_app_index = SYSTEM_CFG->iap_index;
//	uint8_t iap_index = SYSTEM_IAP_NONE;
//	switch(btn_app_index)
//	{
//		case SYSTEM_IAP_APP1:
//			if(SYSTEM_CFG->app1_fw_size != 0 && SYSTEM_CFG->app1_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = btn_app_index;
//			break;
//		case SYSTEM_IAP_APP2:
//			if(SYSTEM_CFG->app2_fw_size != 0 && SYSTEM_CFG->app2_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = btn_app_index;
//			break;
//		case SYSTEM_IAP_APP3:
//			if(SYSTEM_CFG->app3_fw_size != 0 && SYSTEM_CFG->app3_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = btn_app_index;
//			break;
//		default:break;
//	}
//	if(iap_index != SYSTEM_IAP_NONE)
//	{
//		Trace_Log("Read button iap value %d, start load app;\r\n",iap_index);
//		return iap_index;
//	}
//	
//	switch(cfg_app_index)
//	{
//		case SYSTEM_IAP_APP1:
//			if(SYSTEM_CFG->app1_fw_size != 0 && SYSTEM_CFG->app1_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = cfg_app_index;
//			break;
//		case SYSTEM_IAP_APP2:
//			if(SYSTEM_CFG->app2_fw_size != 0 && SYSTEM_CFG->app2_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = cfg_app_index;
//			break;
//		case SYSTEM_IAP_APP3:
//			if(SYSTEM_CFG->app3_fw_size != 0 && SYSTEM_CFG->app3_fw_size <= SYSTEM_APP_FLASH_MAX_SIZE)
//				iap_index = cfg_app_index;
//			break;
//		default:break;
//	}
//	if(iap_index != SYSTEM_IAP_NONE)
//	{
//		Trace_Log("Read system iap value %d, start load app;\r\n",iap_index);
//		return iap_index;
//	}
//	Trace_Log("Read iap value none, if iap did not work, please check firmware size;\r\n");
//	return iap_index;
		return 0;
}
static void Stm32_Clock_Init(uint32_t plln,uint32_t pllm,uint32_t pllp,uint32_t pllq)
{
	HAL_StatusTypeDef ret=HAL_OK;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_OscInitTypeDef RCC_OscInitStruct;
  
	MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0);
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {}
  
	RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState=RCC_HSE_ON;
	RCC_OscInitStruct.HSIState=RCC_HSI_OFF;
	RCC_OscInitStruct.CSIState=RCC_CSI_OFF;
	RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE;

	RCC_OscInitStruct.PLL.PLLN=plln;
	RCC_OscInitStruct.PLL.PLLM=pllm;
	RCC_OscInitStruct.PLL.PLLP=pllp;
	RCC_OscInitStruct.PLL.PLLQ=pllq;

	RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
	RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
	ret=HAL_RCC_OscConfig(&RCC_OscInitStruct);
	if(ret!=HAL_OK) while(1);
  
	RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK|\
                                RCC_CLOCKTYPE_HCLK |\
                                RCC_CLOCKTYPE_D1PCLK1 |\
                                RCC_CLOCKTYPE_PCLK1 |\
                                RCC_CLOCKTYPE_PCLK2 |\
                                RCC_CLOCKTYPE_D3PCLK1);

	RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2; 
	RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2; 
	RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;  
	RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV4; 
	ret=HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
	if(ret!=HAL_OK) while(1);

	__HAL_RCC_CSI_ENABLE() ;
	__HAL_RCC_SYSCFG_CLK_ENABLE() ;  
	HAL_EnableCompensationCell();
}
